using System;
using System.Linq;
using System.Collections.Generic;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using WalkingTec.Mvvm.Core;
using WalkingTec.Mvvm.Core.Extensions;
using WalkingTec.Mvvm.Mvc;
using HengTong.ViewModel.Hr.SysAttendanceRawRecordVms;
using HengTong.Model.Db.Hr;
using HengTong.Model.Db.Hr.Attendance;
using HengTong.Model.Extension;
using HengTong.Model.Util;
using HengTong.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using TiaoTaoHelper.Models;
using TiaoTaoHelper.Wtm.Attributes;
using UUIDNext;


namespace HengTong.Areas.Hr.Controllers
{
    [Area("Hr")]
    [AuthorizeJwtWithCookie]
    [ActionDescription("打卡记录")]
    [ApiController]
    [Route("api/SysAttendanceRawRecord")]
    public partial class SysAttendanceRawRecordController(ILogger<SysAttendanceRawRecordController> logger)
        : BaseApiController
    {
        [ActionDescription("Sys.Search")]
        [HttpPost("Search")]
        public IActionResult Search(SysAttendanceRawRecordSearcher searcher)
        {
            if (ModelState.IsValid)
            {
                var vm = Wtm.CreateVM<SysAttendanceRawRecordListVm>(passInit: true);
                vm.Searcher = searcher;
                return Ok(vm.GetJsonForApi());
            }
            else
            {
                return BadRequest(ModelState.GetErrorJson());
            }
        }

        [ActionDescription("Sys.Get")]
        [HttpGet("{id}")]
        public SysAttendanceRawRecordVm Get(string id)
        {
            var vm = Wtm.CreateVM<SysAttendanceRawRecordVm>(id);
            return vm;
        }

        [ActionDescription("Sys.Create")]
        [HttpPost("Add")]
        [PreventDuplicateSubmit]
        public async Task<IActionResult> Add(SysAttendanceRawRecordVm vm)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState.GetErrorJson());
            }
            else
            {
                await vm.DoAddAsync();
                if (!ModelState.IsValid)
                {
                    return BadRequest(ModelState.GetErrorJson());
                }
                else
                {
                    return Ok(vm.Entity);
                }
            }
        }

        [ActionDescription("Sys.Edit")]
        [PreventDuplicateSubmit]
        [HttpPut("Edit")]
        public async Task<IActionResult> Edit(SysAttendanceRawRecordVm vm)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState.GetErrorJson());
            }
            else
            {
                await vm.DoEditAsync(false);
                if (!ModelState.IsValid)
                {
                    return BadRequest(ModelState.GetErrorJson());
                }
                else
                {
                    return Ok(vm.Entity);
                }
            }
        }

        [HttpPost("BatchDelete")]
        [ActionDescription("Sys.Delete")]
        [PreventDuplicateSubmit]
        public IActionResult BatchDelete(string[] ids)
        {
            var vm = Wtm.CreateVM<SysAttendanceRawRecordBatchVm>();
            if (ids != null && ids.Any())
            {
                vm.Ids = ids;
            }
            else
            {
                return Ok();
            }

            if (!ModelState.IsValid || !vm.DoBatchDelete())
            {
                return BadRequest(ModelState.GetErrorJson());
            }
            else
            {
                return Ok(ids.Count());
            }
        }


        [ActionDescription("Sys.Export")]
        [HttpPost("ExportExcel")]
        public IActionResult ExportExcel(SysAttendanceRawRecordSearcher searcher)
        {
            var vm = Wtm.CreateVM<SysAttendanceRawRecordListVm>();
            vm.Searcher = searcher;
            vm.SearcherMode = ListVMSearchModeEnum.Export;
            return vm.GetExportData();
        }

        [ActionDescription("Sys.CheckExport")]
        [HttpPost("ExportExcelByIds")]
        public IActionResult ExportExcelByIds(string[] ids)
        {
            var vm = Wtm.CreateVM<SysAttendanceRawRecordListVm>();
            if (ids != null && ids.Any())
            {
                vm.Ids = new List<string>(ids);
                vm.SearcherMode = ListVMSearchModeEnum.CheckExport;
            }

            return vm.GetExportData();
        }

        [ActionDescription("Sys.DownloadTemplate")]
        [HttpGet("GetExcelTemplate")]
        public IActionResult GetExcelTemplate()
        {
            var vm = Wtm.CreateVM<SysAttendanceRawRecordImportVm>();
            var qs = new Dictionary<string, string>();
            foreach (var item in Request.Query.Keys)
            {
                qs.Add(item, Request.Query[item]);
            }

            vm.SetParms(qs);
            var data = vm.GenerateTemplate(out string fileName);
            return File(data, "application/vnd.ms-excel", fileName);
        }

        [ActionDescription("Sys.Import")]
        [HttpPost("Import")]
        public ActionResult Import(SysAttendanceRawRecordImportVm vm)
        {
            if (vm != null && (vm.ErrorListVM.EntityList.Count > 0 || !vm.BatchSaveData()))
            {
                return BadRequest(vm.GetErrorJson());
            }
            else
            {
                return Ok(vm?.EntityList?.Count ?? 0);
            }
        }


        [HttpGet("GetSysPersons")]
        public ActionResult GetSysPersons()
        {
            return Ok(DC.Set<SysPerson>().GetSelectListItems(Wtm, x => x.Name));
        }

        /// <summary>
        /// 手动同步海康威视打卡记录
        /// </summary>
        /// <param name="startDate">开始日期(可选,默认昨天)</param>
        /// <param name="endDate">结束日期(可选,默认昨天)</param>
        [ActionDescription("手动同步海康打卡记录")]
        [PreventDuplicateSubmit]
        [HttpPost("[action]")]
        public async Task<Result<object>> SyncHikVisionAttendance([FromBody] SyncAttendanceRequest request)
        {
            var requestId = Guid.NewGuid().ToString("N")[..8];
            logger.LogInformation("手动同步海康打卡记录请求 - RequestId: {RequestId}, StartDate: {StartDate}, EndDate: {EndDate}",
                requestId, request.StartDate, request.EndDate);

            try
            {
                // 默认日期为昨天
                DateTime start = request.StartDate ?? DateTime.Now.AddDays(-1).Date;
                DateTime end = request.EndDate ?? start;

                // 获取配置
                var siteConfig = Wtm.GetSiteConfig();
                var siteConfigControlConfig = siteConfig.ControlConfig;

                if (string.IsNullOrWhiteSpace(siteConfigControlConfig))
                {
                    return new Result<object>("系统JSON配置未设置,请在系统配置中填写相关参数");
                }

                // 解析JSON配置
                var config =
                    JsonSerializer.Deserialize<Dictionary<string, Dictionary<string, string>>>(siteConfigControlConfig);

                // 获取海康威视配置
                if (!config.TryGetValue("HikVision", out var hikConfig) ||
                    !hikConfig.TryGetValue("Host", out string host) ||
                    !hikConfig.TryGetValue("AppKey", out string appKey) ||
                    !hikConfig.TryGetValue("AppSecret", out string appSecret))
                {
                    return new Result<object>("海康威视配置不完整,请检查系统配置");
                }

                logger.LogInformation("海康配置信息 - Host: {Host}, AppKey: {AppKey}", host, appKey);

                var hostParts = host.Split(':');
                string ip = hostParts[0];
                int port = int.Parse(hostParts[1]);

                // 设置平台信息
                HikVisionHttpUtil.SetPlatformInfo(appKey, appSecret, ip, port, true);

                // 预加载员工信息
                logger.LogInformation("预加载员工信息...");
                var personDict = await DC.Set<SysPerson>()
                    .Where(x => x.GetType() == typeof(SysPerson))
                    .Where(p => p.StaffNo != null && p.StaffNo != "")
                    .ToDictionaryAsync(p => p.StaffNo, p => p);

                logger.LogInformation("加载了 {Count} 条员工信息", personDict.Count);

                int totalImported = 0, totalSkipped = 0, totalFailed = 0;
                int totalPersonMatched = 0, totalPersonNotMatched = 0;

                // 需要过滤的设备编码(正门岗)
                var excludedDeviceIds = new HashSet<string>
                {
                    "0bbe2e278a73483b9a4b27b98f2a37ec",
                    "5e84e2f77bc0480b91fd3757f5e6663b"
                };

                // 按天处理
                for (DateTime currentDate = start; currentDate <= end; currentDate = currentDate.AddDays(1))
                {
                    logger.LogInformation("处理 {Date} 的数据", currentDate.ToString("yyyy-MM-dd"));

                    string startTimeStr = currentDate.ToString("yyyy-MM-ddT00:00:00+08:00");
                    string endTimeStr = currentDate.AddDays(1).AddSeconds(-1).ToString("yyyy-MM-ddT23:59:59+08:00");

                    // 查询已导入的记录EventId
                    var existingEvents = await DC.Set<SysAttendanceRawRecord>()
                        .Where(r => r.PunchTime >= currentDate && r.PunchTime < currentDate.AddDays(1))
                        .Where(r => r.RawData != null && r.RawData.Contains("EventId"))
                        .Select(r => r.RawData)
                        .ToListAsync();

                    var existingEventIds = new HashSet<string>();
                    foreach (var rawData in existingEvents)
                    {
                        try
                        {
                            var hikEvent = JsonSerializer.Deserialize<AcsDoorEvent>(rawData);
                            if (hikEvent != null && !string.IsNullOrEmpty(hikEvent.EventId))
                            {
                                existingEventIds.Add(hikEvent.EventId);
                            }
                        }
                        catch (Exception ex)
                        {
                            logger.LogWarning(ex, "解析已存在记录的EventId失败: {RawData}", rawData);
                        }
                    }

                    logger.LogInformation("找到 {Count} 条已导入的记录", existingEventIds.Count);

                    // 分页查询
                    int pageNo = 1;
                    const int pageSize = 1000;
                    bool hasMorePages = true;

                    while (hasMorePages)
                    {
                        var requestParams = new
                        {
                            pageNo = pageNo,
                            pageSize = pageSize,
                            startTime = startTimeStr,
                            endTime = endTimeStr,
                            sort = "eventTime",
                            order = "desc"
                        };

                        string jsonBody = JsonSerializer.Serialize(requestParams);
                        string uri = "/artemis/api/acs/v2/door/events";

                        var response = await HikVisionHttpUtil.HttpPostJsonAsync<AcsDoorEventResponse>(uri, jsonBody);

                        if (response != null && response.Code == "0" && response.Data != null)
                        {
                            var validEvents = response.Data.List
                                .Where(e => !string.IsNullOrEmpty(e.jobNo) &&
                                            !excludedDeviceIds.Contains(e.DevIndexCode))
                                .ToList();

                            logger.LogInformation("本页有效记录: {Count}/{Total}", validEvents.Count,
                                response.Data.List.Count);

                            var recordBatch = new List<SysAttendanceRawRecord>();

                            foreach (var hikEvent in validEvents)
                            {
                                try
                                {
                                    if (existingEventIds.Contains(hikEvent.EventId))
                                    {
                                        totalSkipped++;
                                        continue;
                                    }

                                    existingEventIds.Add(hikEvent.EventId);
                                    personDict.TryGetValue(hikEvent.jobNo, out var person);

                                    var attendanceRecord = new SysAttendanceRawRecord
                                    {
                                        ID = Uuid.NewDatabaseFriendly(Database.SqlServer),
                                        PersonId = person?.ID,
                                        StaffNo = hikEvent.jobNo,
                                        PunchTime = DateTime.Parse(hikEvent.EventTime),
                                        DeviceId = hikEvent.DevIndexCode,
                                        DeviceName = hikEvent.DoorName,
                                        Location = hikEvent.DoorName,
                                        PunchType = hikEvent.InAndOutType == 1 ? "进" :
                                            hikEvent.InAndOutType == 0 ? "出" : "未知",
                                        RecognitionType = "海康威视打卡",
                                        RawData = JsonSerializer.Serialize(hikEvent),
                                        ProcessStatus = person != null ? "已匹配人员" : "未匹配人员",
                                        ProcessTime = DateTime.Now,
                                        Remark = person != null
                                            ? $"已匹配到人员：{person.Name}"
                                            : $"未匹配到人员,原始姓名：{hikEvent.PersonName},工号：{hikEvent.jobNo}"
                                    };

                                    recordBatch.Add(attendanceRecord);

                                    if (person != null)
                                        totalPersonMatched++;
                                    else
                                        totalPersonNotMatched++;

                                    if (recordBatch.Count >= 50)
                                    {
                                        await DC.Set<SysAttendanceRawRecord>().AddRangeAsync(recordBatch);
                                        await DC.SaveChangesAsync();
                                        totalImported += recordBatch.Count;
                                        recordBatch.Clear();
                                    }
                                }
                                catch (Exception ex)
                                {
                                    totalFailed++;
                                    logger.LogError(ex, "处理记录失败 - EventId: {EventId}", hikEvent.EventId);
                                }
                            }

                            if (recordBatch.Count > 0)
                            {
                                await DC.Set<SysAttendanceRawRecord>().AddRangeAsync(recordBatch);
                                await DC.SaveChangesAsync();
                                totalImported += recordBatch.Count;
                            }

                            int totalPages = (response.Data.Total + pageSize - 1) / pageSize;
                            hasMorePages = pageNo < totalPages && response.Data.List.Count >= pageSize;
                            pageNo++;

                            response.Data.List.Clear();
                            GC.Collect();
                        }
                        else
                        {
                            logger.LogError("API返回错误: {Code} - {Message}", response?.Code, response?.Msg);
                            hasMorePages = false;
                        }
                    }
                }

                var result = new
                {
                    StartDate = start.ToString("yyyy-MM-dd"),
                    EndDate = end.ToString("yyyy-MM-dd"),
                    Imported = totalImported,
                    Skipped = totalSkipped,
                    Failed = totalFailed,
                    PersonMatched = totalPersonMatched,
                    PersonNotMatched = totalPersonNotMatched
                };

                logger.LogInformation("同步完成 - 导入: {Imported}, 跳过: {Skipped}, 失败: {Failed}",
                    totalImported, totalSkipped, totalFailed);

                return new Result<object>
                {
                    Code = 200,
                    Message = "同步完成",
                    Data = result
                };
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "同步海康打卡记录异常 - RequestId: {RequestId}", requestId);
                return new Result<object>($"同步失败: {ex.Message}");
            }
        }


        public class SyncAttendanceRequest
        {
            public DateTime? StartDate { get; set; }
            public DateTime? EndDate { get; set; }
        }
    }
}